package com.qd.pay.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.RedisTemplateUtil;
import com.qd.pay.domain.OrderReportDTO;
import com.qd.pay.model.OrderReport;
import com.qd.pay.repository.OrderReportRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Optional;

/**
 * @author sjk
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderReportService {

    private final OrderReportRepository orderReportRepository;
    @Resource
    private RedisTemplateUtil<OrderReport> redisTemplateUtil;

    private static final String PREFIX_ID = "m_order_report_orderId_{0}";

    @Transactional(rollbackFor = Exception.class)
    public OrderReport save(OrderReport model) throws ApiException {
        try {
            if (!orderReportRepository.save(model)) {
                throw new ApiException(ApiResult.error());
            }
            return model;
        } finally {
            clearCache(model);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(OrderReport model) throws ApiException {
        final OrderReport historyModel = Optional.ofNullable(getById(model.getOrderId())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        try {
            if (!orderReportRepository.updateById(model)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean removeById(String orderId) throws ApiException {
        final OrderReport historyModel = Optional.ofNullable(getById(orderId)).orElseThrow(() -> new ApiException("ID不存在,不能删除"));
        try {
            if (!orderReportRepository.removeById(orderId)) {
                throw new ApiException(ApiResult.error());
            }
            return true;
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    public Boolean isExists(String orderId) {
        return orderReportRepository.getBaseMapper().exists(new QueryWrapper<OrderReport>().eq("order_id", orderId));
    }

    public OrderReport getById(String orderId) {
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, orderId);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY * 3), () -> orderReportRepository.getById(orderId), OrderReport.class);
    }

    public OrderReportDTO getByIdDto(String orderId) {
        return Optional.ofNullable(getById(orderId)).map(this::modelToDto).orElse(null);
    }

    public IPage<OrderReportDTO> page(Page<OrderReportDTO> page, OrderReport model) {
        QueryWrapper<OrderReport> queryWrapper = new QueryWrapper<>(model);
        IPage<OrderReport> iPage = orderReportRepository.page(page.convert(this::dtoToModel), queryWrapper);
        return iPage.convert(this::modelToDto);
    }


    private void clearCache(OrderReport model) {
        if (null == model) {
            return;
        }
        String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getOrderId());
        redisTemplateUtil.deleteByKey(key);
    }

    public OrderReportDTO modelToDto(OrderReport model) {
        if (null == model) {
            return null;
        }
        OrderReportDTO dto = new OrderReportDTO();
        dto.setTransactionId(model.getTransactionId());
        dto.setTimeEnd(model.getTimeEnd());
        dto.setBankType(model.getBankType());
        dto.setPayAmount(model.getPayAmount());
        dto.setResultCode(model.getResultCode());
        dto.setAddTime(model.getAddTime());
        dto.setOrderId(model.getOrderId());
        model.freeData();
        return dto;
    }

    public OrderReport dtoToModel(OrderReportDTO dto) {
        if (null == dto) {
            return null;
        }
        OrderReport model = new OrderReport();
        model.setTransactionId(dto.getTransactionId());
        model.setTimeEnd(dto.getTimeEnd());
        model.setBankType(dto.getBankType());
        model.setPayAmount(dto.getPayAmount());
        model.setResultCode(dto.getResultCode());
        model.setAddTime(dto.getAddTime());
        model.setOrderId(dto.getOrderId());
        dto.freeData();
        return model;
    }

    public OrderReport get(OrderReport model) {
        return orderReportRepository.getOne(new QueryWrapper<OrderReport>().setEntity(model), false);
    }

    public OrderReport getOne(String transactionId) {
        QueryWrapper<OrderReport> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transaction_id", transactionId);
        queryWrapper.last("limit 1");
        return orderReportRepository.getOne(queryWrapper, false);
    }

    public boolean exists(String orderId, String resultCode) {
        return orderReportRepository.getBaseMapper().exists(new QueryWrapper<OrderReport>().eq("order_id", orderId).eq("result_code", resultCode));
    }
}